﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace SGUI
{
    public class SGComponent : MonoBehaviour
    {
        public List<SGComponent> Children;
        public SGComponent Parent;
        Dictionary<string, Property> PropertyDic = new Dictionary<string, Property>();
        Dictionary<string, SGComponent> IDDic;
        public virtual void Init()
        {
            this.AddProperty("Id", "", Property_Id_Set);
        }
        public virtual void OnEnter()
        {
            if (this.PropertyValue<string>("Id") != "") 
            {
                gameObject.name = this.PropertyValue<string>("Id");
            }
        }
        public virtual void OnLoad() { }

        public void AddIdRef(string id, SGComponent component)
        {
            if (IDDic == null)
            {
                IDDic = new Dictionary<string, SGComponent>();
            }
            if (IDDic.ContainsKey(id)) 
            {
                IDDic[id] = component;
                return;
            }
            IDDic.Add(id, component);
        }
        public SGComponent GetComponentById(string id)
        {
            if (IDDic != null && IDDic.ContainsKey(id))
            {
                return IDDic[id];
            }
            return null;
        }
        public virtual void GenScript()
        {
            Property pid = this.GetProperty("Id");
            if (pid == null || ((string)pid.Value) == "")
            {
                return;
            }
            UIManager.RootNode.AddIdRef((string)pid.Value, this);
            string ScriptStr = @"var " + pid.Value + " = {     }";
            string PropertyStrs = "";
            int i = 0;
            foreach (KeyValuePair<string, Property> property in PropertyDic)
            {
                i++;
                PropertyStrs += property.Key + " : { get : function(){return GetComponenProperty('" + (string)pid.Value + "','" + property.Key + "'); },set : function(newValue){ SetComponenProperty('" + (string)pid.Value + "','" + property.Key + "',newValue);  } }";
                if (i != PropertyDic.Count)
                {
                    PropertyStrs += ",";
                }
            }
            string DefinePropertyStr = @"Object.defineProperties(" + pid.Value + ",{" + PropertyStrs + "})";
            UIManager.JsEngine.Execute(ScriptStr);
            UIManager.JsEngine.Execute(DefinePropertyStr);
        }
       
        public void Property_Id_Set(object newValue, object oldValue)
        {
            gameObject.name = (string)newValue;
        }

        public LinkedList<SGComponent> GetPath()
        {
            LinkedList<SGComponent> lst = new LinkedList<SGComponent>();
            SGComponent node = this.Parent;
            while (node != null)
            {
                lst.AddLast(node);
                node = node.Parent;
            }
            return lst;
        }
        public void AddChildren(SGComponent component)
        {
            if (this.Children == null)
            {
                this.Children = new List<SGComponent>();
            }
            component.Parent = this;
            component.transform.parent = this.transform;
            component.transform.localPosition = Vector3.zero + new Vector3(0, 0, -0.1f * this.Children.Count);
            this.Children.Add(component);
        }

        public virtual void SetProperty(string k, object v, bool pullEvent = true)
        {
            if (this.PropertyDic.ContainsKey(k))
            {
                if (pullEvent)
                {
                    this.PropertyDic[k].Value = v;
                }
                else
                {
                    this.PropertyDic[k].mValue = v;
                }
            }
            else
            {
                Debug.LogError("设置了一个不存在的属性" + k);
            }
        }
        public virtual void AddProperty(string k, object dv, Property.SetEvent setFn = null, Property.GetEvent getFn = null)
        {
            Property newProperty = new Property();
            this.PropertyDic[k] = newProperty;
            newProperty.Value = dv;
            if (setFn != null)
            {
                newProperty.AddSetEvent(setFn);
            }
            if (getFn != null)
            {
                newProperty.AddGetEvent(getFn);
            }
        }

        public virtual Property GetProperty(string k)
        {
            if (this.PropertyDic.ContainsKey(k))
            {
                return this.PropertyDic[k];
            }
            return null;
        }

        public virtual Property FindProperty(string k) 
        {
            SGComponent CurComponent = this;
            while (CurComponent != null)
            {
                if (CurComponent.PropertyDic!=null&&CurComponent.PropertyDic.ContainsKey(k)) 
                {
                    return CurComponent.PropertyDic[k];
                }
                CurComponent = CurComponent.Parent;
            }

            return null;
        }

        public virtual T PropertyValue<T>(string k) 
        {
           Property p =  this.GetProperty(k);
           if (p == null)
           {
               return default(T);
           }
           else 
           {
               return (T)p.Value;
           }
        }

    }

}